package com.teamwings.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.teamwings.common.aspect.FormControlMap;
import com.teamwings.ctrls.FormComponent;
import com.teamwings.modules.design.vo.FormVo;

import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * JSON转FormVo 工具类
 * 前者与后者结构不对称，不能使用FormVo转为JSON
 */
public class VoUtils {

    //public static ParserConfig fieldConfig = new ParserConfig();
    //static {
    //    fieldConfig.addDeny("label");
    //    fieldConfig.addDeny("key");
    //    fieldConfig.addDeny("model");
    //    fieldConfig.addDeny("options");
    //    fieldConfig.addDeny("columns");
    //    fieldConfig.addDeny("trs");
    //    fieldConfig.addDeny("list");
    //    fieldConfig.addDeny("list");
    //}

    public static FormVo newFormVo(String json) {
        JSONObject obj = JSON.parseObject(json);
        JSONObject objConfig = obj.getJSONObject("config");
        // 转化map数据
        Map<String, Object> mapConfig = JSONObject.parseObject(
                obj.getString("config"),
                new TypeReference<Map<String, Object>>() {
                }
        );

        // 转化list FormComponent数据
        //ParserConfig parserConfig = new ParserConfig();
        //parserConfig.addAccept("label");
        //parserConfig.addAccept("key");
        //parserConfig.addAccept("model");
        //parserConfig.addAccept("options");
        //parserConfig.addAccept("columns");
        //parserConfig.addAccept("trs");
        //parserConfig.addAccept("list");
        //List<FormComponent> list = JSON.parseArray(obj.getString("list"), FormComponent.class, parserConfig);

        // 转化list到具体的FormComponent子类
        JSONArray jsonList = obj.getJSONArray("list");
        List<FormComponent> list = jsonList.parallelStream().map(VoUtils.newFormComponent)
                // 去掉null的控件(不存在于服务器控件类的控件)
                .filter((item) -> item != null)
                .collect(Collectors.toList());

        FormVo formVo = new FormVo();
        formVo.setList(list);
        formVo.setConfig(mapConfig);
        if (obj.containsKey("tableName")) {
            formVo.setTableName(obj.getString("tableName"));
        }
        if (obj.containsKey("tableCname")) {
            formVo.setTableCname(obj.getString("tableCname"));
        }
        if (obj.containsKey("tableTxt")) {
            formVo.setTableTxt(obj.getString("tableTxt"));
        }
        if (obj.containsKey("tableCateId")) {
            formVo.setTableCateId(obj.getString("tableCateId"));
        }
        if (obj.containsKey("tableSourceType")) {
            formVo.setTableSourceType(obj.getString("tableSourceType"));
        }
        if (obj.containsKey("tableHeadId")) {
            formVo.setTableHeadId(obj.getString("tableHeadId"));
        }
        if (obj.containsKey("tableVersion")) {
            formVo.setTableVersion(obj.getString("tableVersion"));
        }
        if (obj.containsKey("isOld")) {
            formVo.setIsOld(obj.getString("isOld"));
        }
        return formVo;
    }

    public static Function<? super Object, FormComponent> newFormComponent = (item) -> {
        JSONObject jsonObject;
        if (item instanceof JSONObject) {
            jsonObject = (JSONObject) item;
        } else {
            jsonObject = JSONObject.parseObject(item.toString());
        }
        String type = jsonObject.getString("type");
        FormComponent comp = null;
        try {
            comp = VoUtils.newFormComponentByType(type);
        } catch (ClassNotFoundException e) {
            // 这个类型不存在于服务器
            return null;
        }
        comp.setType(jsonObject.getString("type"));
        comp.setLabel(jsonObject.getString("label"));
        comp.setModel(jsonObject.getString("model"));
        comp.setKey(jsonObject.getString("key"));
        comp.setOptions(JSONObject.parseObject(
                jsonObject.getString("options"),
                new TypeReference<Map<String, Object>>() {
                }
        ));
        // 2022-02-07, 添加内部字段 internal
        comp.setInternal(JSONObject.parseObject(
                jsonObject.getString("internal"),
                new TypeReference<Map<String, Map>>() {}
        ));

        // 缓存下级JSON
        if (comp.beLayout) {
            comp.setLayoutChildString(jsonObject);
        }
        return comp;
    };

    /**
     * 如果遇到不存在的类型，抛出异常
     *
     * @return
     */
    public static FormComponent newFormComponentByType(String type) throws ClassNotFoundException {
        boolean isLayout = false;
        String clsName = "";
        if (FormControlMap.typeClassMap.containsKey(type)) {
            clsName = FormControlMap.typeClassMap.get(type);
        } else if (FormControlMap.layoutTypeClassMap.containsKey(type)) {
            isLayout = true;
            clsName = FormControlMap.layoutTypeClassMap.get(type);
        }
        FormComponent comp = null;
        // 创建一个控件的子类
        try {
            comp = (FormComponent) Class.forName(clsName).getDeclaredConstructor().newInstance();
        } catch (InstantiationException | IllegalAccessException
                | InvocationTargetException | NoSuchMethodException | ClassNotFoundException e) {
            System.out.println("clsName:" + clsName + "; type: " + type);
            //e.printStackTrace();
            throw new ClassNotFoundException("type: " + type + " 找不到控件类。");
        }
        return comp;
    }


    /**
     * 如果遇到不存在的类型，抛出异常
     *
     * @return
     */
    public static FormComponent newFormComponentByType(String type, Boolean allowNewNoFieldFormComponent) throws ClassNotFoundException {
        boolean isLayout = false;
        String clsName = "";

        if (FormControlMap.typeClassMap.containsKey(type)) {
            clsName = FormControlMap.typeClassMap.get(type);
        } else if (FormControlMap.layoutTypeClassMap.containsKey(type)) {
            isLayout = true;
            clsName = FormControlMap.layoutTypeClassMap.get(type);
        } else if (allowNewNoFieldFormComponent) {
            // 是否允许实例化“数据库没有字段控件”
            clsName = FormControlMap.noFieldClassMap.get(type);
        }
        if (clsName == null) {
            return null;
        }
        FormComponent comp = null;
        // 创建一个控件的子类
        try {
            comp = (FormComponent) Class.forName(clsName).getDeclaredConstructor().newInstance();
        } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException | ClassNotFoundException e) {
            System.out.println("clsName:" + clsName + "; type: " + type);
            throw new ClassNotFoundException("type: " + type + " 找不到控件类。");
        }
        return comp;
    }

    public static FormVo newFormVoAllowNoField(String json) {
        JSONObject obj = JSON.parseObject(json);
        JSONObject objConfig = obj.getJSONObject("config");
        // 转化map数据
        Map<String, Object> mapConfig = JSONObject.parseObject(
                obj.getString("config"),
                new TypeReference<Map<String, Object>>() {
                }
        );

        // 转化list到具体的FormComponent子类
        JSONArray jsonList = obj.getJSONArray("list");
        List<FormComponent> list = jsonList.parallelStream().map(VoUtils.newFormComponentAndAllowNoField)
                // 去掉null的控件(不存在于服务器控件类的控件)
                .filter((item) -> item != null)
                .collect(Collectors.toList());

        FormVo formVo = new FormVo();
        formVo.setList(list);
        formVo.setConfig(mapConfig);
        if (obj.containsKey("tableName")) {
            formVo.setTableName(obj.getString("tableName"));
        }
        if (obj.containsKey("tableCname")) {
            formVo.setTableCname(obj.getString("tableCname"));
        }
        if (obj.containsKey("tableTxt")) {
            formVo.setTableTxt(obj.getString("tableTxt"));
        }
        if (obj.containsKey("tableCateId")) {
            formVo.setTableCateId(obj.getString("tableCateId"));
        }
        if (obj.containsKey("tableSourceType")) {
            formVo.setTableSourceType(obj.getString("tableSourceType"));
        }
        if (obj.containsKey("tableHeadId")) {
            formVo.setTableHeadId(obj.getString("tableHeadId"));
        }
        if (obj.containsKey("tableVersion")) {
            formVo.setTableVersion(obj.getString("tableVersion"));
        }
        if (obj.containsKey("isOld")) {
            formVo.setIsOld(obj.getString("isOld"));
        }
        return formVo;
    }

    public static Function<? super Object, FormComponent> newFormComponentAndAllowNoField = (item) -> {
        JSONObject jsonObject;
        if (item instanceof JSONObject) {
            jsonObject = (JSONObject) item;
        } else {
            jsonObject = JSONObject.parseObject(item.toString());
        }
        String type = jsonObject.getString("type");
        FormComponent comp = null;
        try {
            comp = VoUtils.newFormComponentByType(type, true);
        } catch (ClassNotFoundException e) {
            // 这个类型不存在于服务器
            return null;
        }
        if (comp == null) {
            return null;
        }
        comp.setType(jsonObject.getString("type"));
        comp.setLabel(jsonObject.getString("label"));
        comp.setModel(jsonObject.getString("model"));
        comp.setKey(jsonObject.getString("key"));
        comp.setOptions(JSONObject.parseObject(
                jsonObject.getString("options"),
                new TypeReference<Map<String, Object>>() {
                }
        ));
        // 缓存下级JSON
        if (comp.beLayout) {
            comp.setLayoutChildString(jsonObject);
        }
        return comp;
    };
}
